package android_serialport_api;

import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 串口管理类
 * 1、使用getAllDevices获取所有设备
 * 2、实例化该类，传入设备信息，和频率
 * 3、pushMsg发送信息到串口。
 * 4、收到信息回回调
 * Created by Hello_海生 on 2015/8/13.
 */
public abstract class ChuanKouUtils {
    private SerialPort serialPort;
    private OutputStream outputStream;
    private InputStream inputStream;
    private ReadThread readThread;

    /**
     * 实例化一个 串口对象
     *
     * @param device   通过getAllDevices获取设备信息列表
     * @param baudRate 频率，一般是 9600
     */
    public ChuanKouUtils(DevicesInfo device, int baudRate) {
        try {
            serialPort = new SerialPort(new File(device.path), Integer.decode(baudRate + ""), 0);
            outputStream = serialPort.getOutputStream();    //发送流
            inputStream = serialPort.getInputStream();      //接收流
            //启动接收线程
            readThread = new ReadThread();
            readThread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 发送信息到串口
     */
    public void pushMsg(String mssage) throws Exception {
        //发送数据
        Log.i(ChuanKouUtils.class.getSimpleName(), "发送String：" + mssage);
        sendDataToSerialPort(mssage.getBytes("GBK"));
    }

    /**
     * 发送信息到串口
     */
    public void pushMsg(int[] text) throws Exception {
        byte[] bytes = intToByte(text);
        pushMsg(bytes);
    }

    /**
     * 发送信息到串口
     */
    public void pushMsg(byte[] text) throws Exception {
        //发送数据
        Log.i(ChuanKouUtils.class.getSimpleName(), "发送Byte[]：" + showByte(text, text.length));
        sendDataToSerialPort(text);
    }


    private void sendDataToSerialPort(byte[] bytes)throws Exception{
        outputStream.write(bytes);
        outputStream.flush();
    }


    public static byte[] intToByte(int[] text){
        byte[] bytes = new byte[text.length];
        for (int i=0;i<bytes.length;i++){
            bytes[i] = (byte) text[i];
        }
        return bytes;
    }

    /**
     * 获取所有端口
     */
    public static List<DevicesInfo> getAllDevices() {
        SerialPortFinder mSerialPortFinder = new SerialPortFinder();
        String[] entries = mSerialPortFinder.getAllDevices();
        String[] entryValues = mSerialPortFinder.getAllDevicesPath();

        List<DevicesInfo> list = new ArrayList<>();
        for (int i = 0; i < entries.length; i++) {
            list.add(new DevicesInfo(entries[i], entryValues[i]));
        }
        return list;
    }


    /**
     * 关闭端口
     */
    public void closeSerialPort() {
        if (readThread != null)
            readThread.interrupt();
        if (serialPort != null) {
            serialPort.close();
        }
    }

    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                try {
                    byte[] buffer = new byte[64];
                    if (inputStream == null) return;
                    int size = inputStream.read(buffer);
                    if (size > 0) {
                        onDataReceived(Arrays.copyOf(buffer,size), size);   //回调
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }


    public static String showByte(byte[] text, int nLen) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < nLen; i++) {
            String strHex = Integer.toHexString(text[i]).toUpperCase();

//            if(i % 16 == 0)sb.append("\n");
            if (strHex.length() > 3) sb.append(strHex.substring(6));
            else if (strHex.length() < 2) sb.append("0" + strHex);
            else sb.append(strHex);
            sb.append(" ");

        }
        return sb.toString();
    }


    /**
     * 回调
     */
    protected abstract void onDataReceived(final byte[] buffer, final int size);
}
